/*
 This file 'pager2' is part of Firebird Integrated Solution 1.0

 Copyright (c) 2014 Lincong

 Contact:
 Email: lincong1987@gmail.com

 QQ: 159257119

 See Usage at http://www.cleverlin.com/firebird

 Create date: 2014-12-12 16:54
 */

define(function (require, exports, module) {

	var jQuery = $ = require("jquery");
	var pager2 = {};
	var count = 0;

	/**
	 * i18n 配置
	 * @type {{E1: string}}
	 */
	var message = {
		E1: "Pager2 Error: renderTo is not defined."
	};

	var noop = function () {
	};

	/**
	 * 默认参数
	 * @type {{renderTo: null, url: string, dataType: string, method: string, pageParam: {page: number, size: number, pageParamName: string, sizeParamName: string, totalParamName: string, countParamName: string, root: string}, lang: {first: string, prev: string, next: string, last: string, ellipse: string, loading: string, start: number, end: number}, css: {pager: string}, align: string, href: string, detail: string, param: {}, setParam: Function, onAfterPageClick: Function, onBeforePageClick: Function, onLoad: Function, onComplete: Function, onError: Function, onSuccess: Function, onSearch: Function, onReload: Function}}
	 */
	var defaults = {
		/**
		 * 将要放置分页的容器，可以是字符串、元素、jQ对象
		 */
		renderTo: null,
		/**
		 * 数据请求地址
		 */
		url: "",
		/**
		 * 数据类型
		 */
		dataType: "json",
		/**
		 * 请求方法
		 */
		method: "post",
		/**
		 * 分页参数配置
		 */
		pageParam: {
			page: 1,
			size: 10,
			pageParamName: "page",
			sizeParamName: "size",
			totalParamName: "total",
			countParamName: "count",
			root: "data"
		},
		/**
		 * 杂项，如按钮显示内容，显示数码的个数等
		 */
		lang: {
			// &laquo;&laquo;
			//first: "First",
			//// &laquo;
			//prev: "Previous",
			//// &laquo;
			//next: "Next",
			//// &laquo;&laquo;
			//last: "Last",

			first: "首页",
			prev: "上页",
			next: "下页",
			last: "尾页",

			ellipse: '&hellip;',
			loading: "loading...",
			start: 4,
			end: 4

		},

		show: {
			first: true,
			prev: true,
			next: true,
			last: true,
			detail: true
		},


		/**
		 * 样式配置，有多种样式可选
		 */
		css: {
			// pagination-sm pagination-lg
			pager: "pager"

		},

		align: "left",
		/**
		 * 如果配置，分页可以由地址栏哈希缓存
		 */
		href: "#pager2-url-cache={{page}}",
		/**
		 * 详细数据显示，可以通过通配符模版，提供4个通配符total page count size
		 */
		detail: "<li class='disabled'><span class='pager2-detail label label-default'>{{total}}条 {{page}}/{{count}}页</span></li>",
		/**
		 * 分页输数据请求的参数，是一个k-v键值对
		 */
		param: {},
		/**
		 * 在doSearch前调用，可以设置param或处理其他业务
		 */
		setParam: noop,
		/**
		 * 分页按钮点击后触发
		 */
		onAfterPageClick: noop,
		/**
		 * 分页按钮点击前触发
		 */
		onBeforePageClick: noop,
		/**
		 * 数据装载前触发
		 */
		onLoad: noop,
		/**
		 * 对象初始化后触发
		 */
		onInit: noop,
		/**
		 * 数据加载完成后调用
		 */
		onComplete: noop,
		/**
		 * 数据加载失败
		 */
		onError: noop,
		/**
		 * 数据加载成功
		 */
		onSuccess: noop,
		/**
		 * 搜索
		 */
		onSearch: noop,
		/**
		 * 重新加载
		 */
		onReload: noop
	};

	/**
	 * 分页对象
	 * @param options
	 * @constructor
	 */
	function Pager2(options) {

		var options = this.options = $.extend(true, {}, defaults, options);

		if (!options.renderTo) {
			firebird.error(message.E1);
			return;
		}

		if ($(options.renderTo).data("instance")) {
			return $(options.renderTo).data("instance");
		}

		$(options.renderTo).data("instance", this);

		this.onAfterPageClick = options.onAfterPageClick || noop;
		this.onBeforePageClick = options.onBeforePageClick || noop;
		this.onLoad = options.onLoad || noop;
		this.onComplete = options.onComplete || noop;
		this.onError = options.onError || noop;
		this.onSuccess = options.onSuccess || noop;
		this.onInit = options.onInit || noop;

		// 埋点计时
		this.timer = {
			count: 0,
			request: {
				_start: new Date(),
				_end: new Date()
			},
			process: {
				_start: new Date(),
				_end: new Date()
			}
		};
		this.pageCache = firebird.url.getParameter("pager2-url-cache");

		this.init.apply(this, []);
		count++;
	}

	/**
	 * 分页原型
	 * @type {{load: Function, hasError: Function, _onSuccess: Function, processData: Function, renderPageBar: Function, renderButton: Function, doSearch: Function, doReload: Function, goto: Function, next: Function, prev: Function}}
	 */
	Pager2.prototype = {

		/**
		 * 初始化
		 */
		init: function () {
			this.onInit.apply(this, []);
			this.load.apply(this, []);
		},

		/**
		 * 加载数据
		 */
		load: function () {

			var me = this;

			this.pageParam = {};
			this.pageParam[this.options.pageParam.pageParamName] = this.options.pageParam[this.options.pageParam.pageParamName];
			this.pageParam[this.options.pageParam.sizeParamName] = this.options.pageParam[this.options.pageParam.sizeParamName];

			if (this.pageCache && this.pageCache != "") {
				this.pageParam[this.options.pageParam.pageParamName] = this.options.pageParam[this.options.pageParam.pageParamName] = this.pageCache;
				this.pageCache = null;
			}

			var param = jQuery.param(jQuery.extend({}, this.pageParam, this.options.param));

			this.timer.count++;
			// 埋点计时
			this.timer.request._start = new Date().getTime();
			//
			this.onLoad.apply(this, [param]);

			// $(this.options.renderTo).html(me.options.lang.loading);

			jQuery.ajax({
				dataType: this.options.dataType,
				url: this.options.url,
				type: this.options.method,
				data: param,
				complete: function () {
					me.options.onComplete.apply(me, arguments);
				},
				error: function (e) {
					me.onError.apply(me, arguments);
				},
				success: function (json) {
					// 埋点计时
					me.timer.request._end = new Date().getTime();
					firebird.info("\nPager2 Technical Statistics: \n" +
						"The #" + me.timer.count + " Request&Response\n" +
						">request  start  at " + firebird.date.format({
							time: me.timer.request._start,
							format: "$HH:$mm:$ss.$sss\n"
						}) +
						">response loaded at " + firebird.date.format({
							time: me.timer.request._end,
							format: "$HH:$mm:$ss.$sss\n"
						}) +
						">network time consuming " + (me.timer.request._end - me.timer.request._start) + "ms");

					me.hasError.apply(me, [json]) ? me.onError.apply(me, [json]) : me._onSuccess.apply(me, [json]);
				}
			});

		},

		/**
		 * 检测返回的数据是否有错误
		 * @param json
		 * @returns {boolean}
		 */
		hasError: function (json) {
			return (json.errCode || json.errMsg || json.errStack) ? true : false;
		},

		/**
		 * 数据获取成功后调用
		 * @param json
		 * @private
		 */
		_onSuccess: function (json) {
			var me = this;
			// 埋点计时
			me.timer.process._start = new Date();
			this.processData.apply(this, [json]);
			this.onSuccess.apply(this, [json, me]);
			this.renderPageBar.apply(this, [json]);
			// 埋点计时
			me.timer.process._end = new Date();
			firebird.info("\nPager2 Technical Statistics: \n" +
				"The #" + me.timer.count + " Data Process\n" +
				">data process start at " + firebird.date.format({
					time: me.timer.process._start,
					format: "$HH:$mm:$ss.$sss\n"
				}) +
				">data process end at " + firebird.date.format({
					time: me.timer.process._end,
					format: "$HH:$mm:$ss.$sss\n"
				}) +
				">data process time consuming " + (me.timer.process._end - me.timer.process._start) + "ms");
		},

		/**
		 * 数据预处理
		 * @param json
		 */
		processData: function (json) {
			var me = this;
			var options = this.options;
			var size = options.pageParam[options.pageParam.sizeParamName];
			var page = options.pageParam[options.pageParam.pageParamName];
			var total = options.pageParam[options.pageParam.totalParamName] = json[options.pageParam.totalParamName];
			var count = options.pageParam[options.pageParam.countParamName] = Math.ceil(options.pageParam[options.pageParam.totalParamName] / options.pageParam[options.pageParam.sizeParamName]);

			// 修正
			if (page > count) {
				page = options.pageParam[options.pageParam.pageParamName] = count;
			}

			var r1 = parseInt((page - 1) * size, 10) + 1;
			var r2 = parseInt(r1, 10) + parseInt(size, 10) - 1;

			if (total < r2) {
				r2 = total;
			}

			if (json && json[options.pageParam.root]) {
				var rownums = [];
				for (var i = r1; i <= r2; i++) {
					rownums.push(i);
				}
				$.each(json[options.pageParam.root], function (i, n) {
					n._rownum = rownums[i];
				});
			}

		},
		/**
		 * 渲染分页栏
		 * @param json
		 */
		renderPageBar: function (json) {
			var me = this;
			var options = this.options;

			var size = options.pageParam[options.pageParam.sizeParamName];
			var page = options.pageParam[options.pageParam.pageParamName];
			var total = options.pageParam[options.pageParam.totalParamName] = json[options.pageParam.totalParamName];//(data.pagination && data.pagination.total) || data.rowTotal || data.total || (data[options.record] && data[options.record].length) || 0;
			var count = options.pageParam[options.pageParam.countParamName] = Math.ceil(options.pageParam[options.pageParam.totalParamName] / options.pageParam[options.pageParam.sizeParamName]);

			// 修正
			if (page > count) {
				page = options.pageParam[options.pageParam.pageParamName] = count;
			}

			firebird.info("Pager2 info: total items: " + total + "; size: " + size + "; page: " + page + "; so page count is: " + count);

			var $bar = $(this.options.renderTo).data("instance", this).css({
				clear: "both"
			});

			//$bar.html(me.options.lang.loading);

			var $cont = $("<ul />", {
				"class": options.css.pager,
				css: {
					float: "left"
				}
			});

			$cont.append(options.show.first === true ? this.renderButton("first") : "", options.show.prev === true ? this.renderButton("prev") : "");

			// var start = options.lang.start,
			// 	end = options.lang.end;


			// if (page > 4) {
			// 	start = page - 4;
			// 	end = page + 4;
			// }
			// if (end > count) {
			// 	start = count - 8;
			// 	end = count;
			// }
			// if (start < 1) {
			// 	start = 1;
			// }

			// 设定需要显示的 页码 ， 默认为 1 到 总页数
			var start = page - options.lang.start,
				end = page + options.lang.end;

			// 当 当前页 为 1 时
			if (page === 1 || start <= 0) {
				start = 1;
			}

			// 当总页数大于 range end 时
			if (end > count) {
				end = count;
			}

			// count;
			// start;
			// page;
			// end;

			for (var _page = start; _page <= end; _page++) {
				$cont.append(me.renderButton("page", _page));
			}

			$cont.append(options.show.next === true ? this.renderButton("next") : "", options.show.last === true ? this.renderButton("last") : "");

			$bar.html($cont);

			if (options.show.detail === true) {
				$bar.append($("<ul />", {
					"class": options.css.pager,
					css: {
						float: "right"
					},
					html: this.options.detail
						.replace(/\{\{total\}\}/g, total)
						.replace(/\{\{page\}\}/g, page)
						.replace(/\{\{size\}\}/g, size)
						.replace(/\{\{count\}\}/g, count)
				}));
			}


			/**
			 * 绑定分页栏点击事件
			 */
			$bar.off("click").on("click", "a", function (e) {

				var ac = $(this).data("ac");

				if ($(this).hasClass("")) {
				}

				me.onBeforePageClick.apply(me, [ac, $(this).data("page")]);

				if (ac === "page") {
					me.goto.apply(me, [$(this).data("page")]);
				}

				if (ac === "first") {
					me.goto.apply(me, [1]);
				}

				if (ac === "prev") {
					me.goto.apply(me, [page <= 1 ? 1 : (page - 1)]);
				}

				if (ac === "next") {
					me.goto.apply(me, [page >= count ? page : (page + 1)]);
				}

				if (ac === "last") {
					me.goto.apply(me, [count]);
				}

				me.onAfterPageClick.apply(me, [ac, $(this).data("page")]);

				return e.preventDefault();
			});
		},

		/**
		 * 渲染按钮
		 * @param ac
		 * @param targetPage
		 * @returns {*|jQuery|HTMLElement}
		 */
		renderButton: function (ac, targetPage) {
			var me = this;
			var options = this.options;
			var page = options.pageParam[options.pageParam.pageParamName];
			var count = options.pageParam[options.pageParam.countParamName];
			var label = "";
			var className = "";
			switch (ac) {
				case "first":
					label = options.lang.first;
					targetPage = 1;
					if (page === 1) {
						className = "disabled";
					}
					break;
				case "prev":
					label = options.lang.prev;
					targetPage = page <= 1 ? 1 : (page - 1);
					if (page === 1) {
						className = "disabled";
					}
					break;
				case "next":
					label = options.lang.next;
					targetPage = page >= count ? page : (page + 1);
					if (page === count) {
						className = "disabled";
					}
					break;
				case "last":
					label = options.lang.last;
					targetPage = count;
					if (page === count) {
						className = "disabled";
					}
					break;
				case "page":
					label = targetPage;
					if (page === targetPage) {
						className = "active";
					}
					break;
			}

			return $("<li class='{{class}}'><a data-ac='{{ac}}' data-page='{{page}}' href='{{href}}' title='{{title}}'>{{label}}</a></li>"
				.replace(/\{\{href\}\}/, options.href.replace(/\{\{page\}\}/, targetPage))
				.replace(/\{\{label\}\}/, options.lang[ac] || targetPage)
				.replace(/\{\{title\}\}/, "转到第 " + targetPage + " 页")
				.replace(/\{\{ac\}\}/, ac)
				.replace(/\{\{page\}\}/, targetPage)
				.replace(/\{\{class\}\}/, className));

		},

		/**
		 * 搜索
		 */
		doSearch: function () {
			var me = this;
			me.options.pageParam[me.options.pageParam.pageParamName] = 1;
			me.options.setParam();
			me.load();
		},

		/**
		 * 重新加载
		 */
		doReload: function () {
			var me = this;
			me.load();
		},

		/**
		 * 转到某一页
		 * @param page
		 */
		goto: function (page) {
			var me = this;
			me.options.pageParam[me.options.pageParam.pageParamName] = page;
			me.load();
		},

		/**
		 * 下一页
		 */
		next: function () {
			var me = this;
			var page = me.options.pageParam[me.options.pageParam.pageParamName];
			var count = me.options.pageParam[me.options.pageParam.countParamName];
			me.options.pageParam[me.options.pageParam.pageParamName] = page === count ? page : page + 1;
			me.load();
		},

		/**
		 * 上一页
		 */
		prev: function () {
			var me = this;
			var page = me.options.pageParam[me.options.pageParam.pageParamName];
			me.options.pageParam[me.options.pageParam.pageParamName] = page === 1 ? 1 : page - 1;
			me.load();
		}

	};

	// 装载
	pager2.Pager2 = Pager2;

	/**
	 * 封装jQuery插件
	 * @param options
	 */
	jQuery.fn.pager2 = function (options) {
		$(this).data({
			instance: new Pager2(options)
		});
	};

	// 对外接口
	module.exports = pager2;
});

